package com.rop.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.rop.model.system.SysUser;
import com.rop.model.vo.LoginVo;
import com.rop.model.vo.RouterVo;
import com.rop.model.vo.SysUserQueryVo;
import com.rop.result.ResultCodeEnum;
import com.rop.system.exception.BizException;
import com.rop.system.mapper.SysUserMapper;
import com.rop.system.service.SysMenuService;
import com.rop.system.service.SysUserService;
import com.rop.util.JWTConstant;
import com.rop.util.JwtHelper;
import com.rop.util.MD5;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author rop
 * @since 2023-04-14
 */
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private SysMenuService sysMenuService;

    /**
     * 条件分页查询
     *
     * @param pageParam      分页参数
     * @param sysUserQueryVo 查询条件
     * @return 返回的结果
     */
    @Override
    public IPage<SysUser> getList(Page<SysUser> pageParam, SysUserQueryVo sysUserQueryVo) {
        return baseMapper.getList(pageParam, sysUserQueryVo);
    }

    /**
     * 修改用户状态
     *
     * @param id     用户id
     * @param status 状态
     * @return 修改结果
     */
    @Override
    public boolean updateStatus(Long id, Integer status) {
        return sysUserMapper.updateStatus(id, status) > 0 ? Boolean.TRUE : Boolean.FALSE;
    }

    /**
     * 用户登录
     *
     * @param loginVo vo
     * @return 登录，返回token
     */
    @Override
    public String login(LoginVo loginVo) {
        // 根据username查询数据
        QueryWrapper<SysUser> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("username", loginVo.getUsername());
        SysUser sysUser = baseMapper.selectOne(userQueryWrapper);

        // 前置校验
        verifyUserInfo(loginVo, sysUser);

        //根据username和userId生成token字符串，返回
        return JwtHelper.createToken(Long.parseLong(sysUser.getId()), sysUser.getUsername());
    }

    @Override
    public Map<String, Object> info(HttpServletRequest request) {
        // 获取请求头token字符串
        String token = request.getHeader("token");
        // 从token字符串获取用户名称（id）
        Long userId = JwtHelper.getUserId(token);
        String username = JwtHelper.getUsername(token);
        //根据用户名称获取用户信息 （基本信息 菜单权限 按钮权限）
        SysUser sysUser = baseMapper.selectById(userId);

        // 基本信息数据
        Map<String, Object> map = new HashMap<>();
        map.put(JWTConstant.NAME, username);
        map.put(JWTConstant.AVATAR, sysUser.getHeadUrl());
        map.put(JWTConstant.ROLES, "[\"admin\"]");

        List<RouterVo> routerVos = sysMenuService.getUserMenuList(userId);
        // 菜单权限数据
        map.put(JWTConstant.ROUTERS, routerVos);

        List<String> permsList = sysMenuService.getUserButtonList(userId);
        // 按钮权限数据
        map.put(JWTConstant.BUTTONS, permsList);

        return map;
    }

    /**
     * 用户登录校验：1.是否存在用户 2.密码是否正确 3.用户是否可用
     *
     * @param loginVo 登录vo
     * @param sysUser 用户实体
     */
    private void verifyUserInfo(LoginVo loginVo, SysUser sysUser) {
        // 如果查询为空
        if (Objects.isNull(sysUser)) {
            BizException.error(ResultCodeEnum.ACCOUNT_ERROR.getCode(), ResultCodeEnum.ACCOUNT_ERROR.getMsg());
        }

        // 判断密码是否一致
        String password = loginVo.getPassword();
        // 加密
        String passwordWithEncrypt = MD5.encrypt(password);
        if (!Objects.equals(passwordWithEncrypt, sysUser.getPassword())) {
            BizException.error(ResultCodeEnum.PASSWORD_ERROR.getCode(), ResultCodeEnum.PASSWORD_ERROR.getMsg());
        }

        // 判断用户是否可用
        if (Objects.equals(sysUser.getStatus(), 0)) {
            BizException.error(ResultCodeEnum.ACCOUNT_STOP.getCode(), ResultCodeEnum.ACCOUNT_STOP.getMsg());
        }
    }
}
